package com.kehutong.admin.controler;

import java.util.*;
import java.util.stream.Collectors;

import com.kehutong.admin.entity.*;
import com.kehutong.admin.service.RoleService;
import com.kehutong.admin.service.UserHelper;
import com.kehutong.common.DoveClient;
import org.coraframework.authz.HasPermission;
import org.coraframework.inject.Inject;
import org.coraframework.json.JSONArray;
import org.coraframework.json.JSONObject;
import org.coraframework.mvc.MvcAction;
import org.coraframework.mvc.http.ReqMapping;
import org.coraframework.mvc.http.result.JSONResult;
import org.coraframework.mvc.http.result.Result;
import org.coraframework.orm.Pool;
import org.coraframework.orm.jdbc.JdbcSession;
import org.coraframework.orm.jdbc.Page;
import org.coraframework.orm.jdbc.execute.entity.FindArray;
import org.coraframework.orm.jdbc.execute.entity.FindPage;
import org.coraframework.threadpool.ThreadPool;
import org.coraframework.util.Objects;

import com.kehutong.common.entity.Root;
import com.kehutong.common.util.Token;

@MvcAction
@ReqMapping("/admin/sys/role")
public class RoleController {

    @Inject
    private JdbcSession jdbcSession;
    @Inject
	private DoveClient doveClient;
    @Inject
    private UserHelper userHelper;
    @Inject
    private RoleService roleService;
    @Inject
    private ThreadPool threadPool;

    @ReqMapping("/synRoles")
    public Object synRoles(JSONObject jsonObject){
        threadPool.execute(()-> {
            roleService.synRoles(jsonObject);
        });
        return Result.success();
    }

    @HasPermission("sys:role:view")
    @ReqMapping("/list")
    public Object list(Token token, JSONObject jsonObject) throws Exception {
    	FindPage<Role> find = jdbcSession.findPage(Role.class)
    			.eq("deleted", false)
				.like(jsonObject, "name");
    	
		if (Root.isRoot(token.getUuid()) || Objects.isEmpty(token.getCompanyNo())) {
//			find.isNull("companyNo");
		} else {
			find.eq("companyNo", token.getCompanyNo());
		}

        Page<Role> page = find.page(jsonObject).exe();

		List<Role> roles = page.getList();
        for (Role role: roles) {
            getUser(role);

            Set<String> ids = userHelper.getTopMenuIds(token.getRoles());

            List<Menu> microApps = jdbcSession.findArray(Menu.class)
                    .in("id", ids)
                    .eq("deleted", false)
                    .exe();

            List<String> appNames = microApps.stream().map(Menu::getName).collect(Collectors.toList());
            role.setAppNames(appNames);

            List<RoleItem> items = jdbcSession.findArray(RoleItem.class)
                    .in("id", role.getItems())
                    .exe();

            role.setRoleItems(items);
        }
        page.setList(roles);

        return Result.success(page);
    }

    @HasPermission("sys:role:view")
    @ReqMapping("/get")
//    public Object getById(Role role) {
//        return role;
//    }
    public Object get(JSONObject jsonObject) throws Exception {
        Role role = Pool.get(Role.class, jsonObject.getString("id"));
        getUser(role);

        List<RoleItem> items = jdbcSession.findArray(RoleItem.class)
                .in("id", role.getItems())
                .exe();
        role.setRoleItems(items);

        return Result.success(role);
    }

//    @HasPermission("sys:role:edit")
    @ReqMapping("/save")
//    public Object save(Token token, JSONObject jsonObject) {
//    	Role role = Pool.newInstance(Role.class);
//    	JSONResult rs = setProperty(token, role, jsonObject);
//    	if (rs.isOk()) {
//    		jdbcSession.insert(role);
//    	}
//
//        return rs;
//    }
    public Object save(Token token, JSONObject jsonObject) throws Exception {
        Role role = Pool.newInstance(Role.class);

		JSONResult check = setProperty(token, role, jsonObject, true);
		if(Objects.nonNull(check)){
			return check;
		}

		// 处理角色节点
        updateItems(token, role, jsonObject);

        JSONObject result = updateRole(role, jsonObject);
        if (result.getIntValue("code") != 200) {
            return Result.error(0 , result.getString("message"));
        }

        jdbcSession.insert(role);

        return Result.success();
    }

    @HasPermission("sys:role:edit")
    @ReqMapping("/update")
//    public ActionResult<String> update(Token token, JSONObject jsonObject) {
//    	Role role = Pool.get(Role.class, jsonObject.getString("id"));
//    	JSONResult rs = setProperty(token, role, jsonObject);
//
//    	if (rs.isOk()) {
//    		jdbcSession.updateById(role);
//    	}
//
//        return rs;
//    }
	public Object update(Token token, JSONObject jsonObject) throws Exception {
        Role role = Pool.get(Role.class, jsonObject.getString("id"));

		JSONResult check = setProperty(token, role, jsonObject, false);

		if(Objects.nonNull(check)){
			return check;
		}

        // 处理角色节点
        updateItems(token, role, jsonObject);

        JSONObject result = updateRole(role, jsonObject);
        if (result.getIntValue("code") != 200) {
            return Result.error(0 , result.getString("message"));
        }

        jdbcSession.updateById(role);

        return Result.success();
    }

    @HasPermission("sys:role:edit")
    @ReqMapping("/delete")
//    public ActionResult<String> deleteById(Role role) {
//    	role.setDeleted(true);
//
//    	jdbcSession.updateById(role);
//
//
//        return Result.success();
//    }
	public Object delete(Token token, JSONObject jsonObject) throws Exception {
        Role role = Pool.get(Role.class, jsonObject.getString("id"));
        role.setDeleted(true);

        JSONObject result = updateRole(role, jsonObject);
        if (result.getIntValue("code") != 200) {
            return Result.error(0 , result.getString("message"));
        }

        jdbcSession.updateById(role);

        return Result.success();
    }
    
    @HasPermission("sys:role:edit")
    @ReqMapping("/authorization")
    public Object authorization(JSONObject jsonObject) throws Exception {
        Role role = Pool.get(Role.class, jsonObject.getString("id"));

        JSONObject result = updateRole(role, jsonObject);
        if (result.getIntValue("code") != 200) {
            return Result.error(0 , result.getString("message"));
        }

        return Result.success();
    }

    private JSONResult setProperty(Token token, Role item, JSONObject jsonObject, boolean isSave) {

		if (Objects.nonEmpty(token.getUuid()) && Root.isRoot(item.getId()) && !Root.isRoot(token.getUuid())) {
			return Result.error(1002, "不允许修改 [系统管理员] 角色");
		}

        FindArray<Role> find = jdbcSession.findArray(Role.class)
                .eq("deleted", false)
                .eq(jsonObject,"name");

        if (Root.isRoot(token.getUuid()) || Objects.isEmpty(token.getCompanyNo())) {
//            find.isNull("companyNo");
        } else {
            find.eq("companyNo", token.getCompanyNo());
        }

		if(!isSave){
		    find.noEq("id", item.getId());
        }

        List<Role> roles = find.exe();

        if(Objects.nonEmpty(roles)){
            return Result.error(0, "当前角色名称已存在，请修改后重试");
        }

        if(Objects.nonEmpty(token.getCompanyNo())){
            item.setCompanyNo(token.getCompanyNo());
        }
        if(Objects.nonEmpty(token.getCompanyName())){
            item.setCompanyName(token.getCompanyName());
        }
    	String data_scope = jsonObject.getString("data_scope");
        item.setData_scope(data_scope);

    	JSONArray manageDepartment = jsonObject.getJSONArray("manageDepartment");
    	if(data_scope.equals("3") && Objects.nonEmpty(manageDepartment)){
            item.setManageDepartment(JSONObject.parseArray(manageDepartment.toJSONString(), String.class));
        }else{
    	    item.setManageDepartment(null);
        }

    	item.setName(jsonObject.getString("name"));
    	item.setRemarks(jsonObject.getString("remarks"));
        item.setBusinessState(jsonObject.getBooleanValue("businessState"));
        item.setFrontPageState(jsonObject.getBooleanValue("frontPageState"));
        item.setNewsletterState(jsonObject.getBooleanValue("newsletterState"));
        item.setSettingState(jsonObject.getBooleanValue("settingState"));

    	item.setDeleted(false);

    	return null;
	}

	 private List<String> getMenus(JSONObject jsonObject) {
 		JSONArray jsonArray = jsonObject.getJSONArray("menus");

 		Set<String> menuList = new LinkedHashSet<>();
 		for (int i = 0; i < jsonArray.size(); i ++) {
 			Menu menu = Pool.get(Menu.class, jsonArray.getString(i));
 			if (menu != null && !menu.isDeleted()) {
 				menuList.add(menu.getId());
 			}
 		}

 		return new ArrayList<>(menuList);
 	}

 	private void getUser(Role role) throws Exception {
        JSONObject result = doveClient.post("/kht-bin/auth/user/get_users", http->{
            JSONObject body = new JSONObject();
            body.put("roles", role.getId());
            http.setBody(body.toJSONString());
        });

       if (result.getIntValue("code") == 200) {
           JSONArray data = result.getJSONArray("data");
           if(Objects.nonEmpty(data)){
               List<String> ids = new ArrayList<>();
               List<String> names = new ArrayList<>();
               for (int i = 0; i < data.size(); i ++) {
                   JSONObject item = data.getJSONObject(i);
                   ids.add(item.getString("id"));
                   names.add(item.getString("name"));
               }
               role.setEmployeeNo(ids);
               role.setEmployeeName(names);
           }
       }
    }

    private void updateItems(Token token, Role role, JSONObject jsonObject) throws Exception {
    	Set<String> menuIds = new HashSet<>();
    	List<String> items = new ArrayList<>();
        JSONArray jsonArray = jsonObject.getJSONArray("roleItem");
        for (int i = 0; i < jsonArray.size(); i ++) {
            JSONObject json = jsonArray.getJSONObject(i);
            final String id = json.getString("id");
            RoleItem item;
            if (Objects.isEmpty(id)) {
                item = Pool.newInstance(RoleItem.class);
            } else {
                item = Pool.get(RoleItem.class, id);
            }
            item.setRoleId(role.getId());
            item.setMenuId(json.getString("menuId"));
            item.setType(json.getString("type"));
			List<String> ids = new ArrayList<>();
            if(Objects.equal(item.getType(),"2")){
                Set<String> tokenMenus = userHelper.getMenuIds(token.getRoles(), true);
                List<Menu> menus = jdbcSession.findArray(Menu.class)
						.findInSet("parent_ids", json.getString("menuId"))
                        .in("id", tokenMenus)
                        .eq("deleted", false)
                        .exe();
                ids = menus.stream().map(Menu::getId).collect(Collectors.toList());
                ids.add(json.getString("menuId"));
            }else if(Objects.equal(item.getType(),"3")){
                if(Objects.nonEmpty(json.getJSONArray("menus"))){
                    ids = JSONObject.parseArray(json.getJSONArray("menus").toJSONString(), String.class);
                    ids.add(json.getString("menuId"));
                }
            }
			item.setMenus(ids);
            menuIds.add(Root.ROOT_ID);
			menuIds.addAll(ids);
            items.add(item.getId());

            if (Objects.isEmpty(id)) {
                jdbcSession.insert(item);
            } else {
                jdbcSession.updateById(item);
            }
        }
        role.setItems(items);
        role.setMenus(new ArrayList<>(menuIds));
    }

    private JSONObject updateRole(Role role, JSONObject jsonObject) throws Exception {
        JSONObject rs = doveClient.post("/kht-bin/auth/user/update_role", http->{
            JSONObject body = new JSONObject();
            body.put("roleId" , role.getId());
            body.put("newEmployees", jsonObject.getJSONArray("newEmployees"));
            body.put("oldEmployees", jsonObject.getJSONArray("oldEmployees"));
            http.setBody(body.toJSONString());
        });

        return rs;
    }
}
